
#ifndef TVEC_H
#define TVEC_H

#include "tclib.h"

//basic vector class implementation, which static Allocator selection support.
//used by tcrt to implement atexit command stack.
//should behave as per normal stl vector, but not all members defined.

namespace tstd
{
	template <class T, class Allocator> class vector
	{
	public:

		typedef T value_type;
		typedef T* pointer;
		typedef T& reference;
		typedef const T& const_reference;

		typedef size_t size_type;
		typedef int difference_type;

		typedef pointer iterator;

	private:
		void bcheck(size_type i) { assert(mBegin + i < mEnd, "vector bounds check failed"); }
		void ctor(pointer i)
		{	
			new(i) T();
		}
		void ctor(iterator b, iterator e)
		{
			iterator i = b;
			while(i<e)
			{
				ctor(i); ++i;
			}
		}
		void dtor(pointer i)
		{
			i->~T();
		}
		void dtor(iterator b, iterator e) 
		{
			iterator i = b; 
			while(i<e) 
			{
				dtor(i); ++i;
			}
		}
		T* allocn(size_type n)
		{
			return reinterpret_cast<T*>(Allocator::allocate( sizeof(T)*n )); 
		}
		void free(T* p) { Allocator::deallocate(p); }
		void grow()
		{
			size_type s = 2*capacity(); //double in size for each grow
			if(s == 0) s = 3; //handle edge cases

			T* pGrown = allocn(s);
			//make sure objects copy properly
			{
				size_t num = size();
				for(size_t i=0; i<num; ++i)
					pGrown[i] = mBegin[i];
			}
			//update internals
			mEnd = pGrown + (mEnd - mBegin);
			//release old memory
			free(mBegin);
			mBegin = pGrown;
			mCapacity = pGrown + s;			
		}

	public:

		iterator begin() { return mBegin; }
		iterator end() { return mEnd; }

		size_type size() { return mEnd - mBegin; }
		size_type capacity() { return mCapacity - mBegin; }

		bool empty() { return mBegin == mEnd; }

		reference operator[](size_type n) { bcheck(n); return mBegin[n]; }
		const_reference operator[](size_type n) const { bcheck(n); return mBegin[n]; }

		vector() 
			: mBegin(NULL)
			, mEnd(NULL)
			, mCapacity(NULL)
		{	}

		vector(size_type n)
		{
			mBegin = allocn(n);
			mEnd = mBegin;
			mCapacity = mBegin + n;
		}

		vector(size_type n, const T& t)
		{
			mBegin = allocn(n);
			mEnd = mBegin;
			mCapacity = mBegin + n;

			for(int i=0; i<n; ++i)
				mBegin[i] = t;
		}

		~vector()
		{
			dtor(mBegin, mEnd);
			free(mBegin);
		}

		void clear()
		{
			dtor(mBegin, mEnd);
			mEnd = mBegin;
		}

		void push_back(const T& a)
		{
			if(mEnd == mCapacity)
				grow();

			*mEnd = a;
			++mEnd;
		}

		void pop_back()
		{
			assert(mEnd > mBegin, "too many pops");
			--mEnd;
			dtor(mEnd);
		}

	private:
		T* mBegin;
		T* mEnd;
		T* mCapacity;
	
	};

};

#endif